package com.seventhdawn.gwt.rcx.rebind;

import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.user.rebind.rpc.UberProxyCreator;

/**
 * Deferred binding generator for producing asynchronous client-side
 * implementations of {@link com.google.gwt.user.client.rpc.RemoteService
 * RemoteService} interfaces.
 * <p>
 * Resulting service proxy implementations can be customized via annotations:
 * <ul>
 * <li>{@link com.seventhdawn.gwt.rcx.client.annotation.ClientProxySuperclass
 * ClientProxySuperclass} for setting the proxy superclass
 * <li>{@link com.seventhdawn.gwt.rcx.client.annotation.CustomSerializableRoots
 * CustomSerializableRoots} for adding custom serializable root types to the
 * serialization policy
 * </ul>
 * 
 * @see UberProxyCreator
 * @author vojtech.szocs
 */
public class UberServiceInterfaceProxyGenerator extends Generator {

    @Override
    public String generate(TreeLogger logger, GeneratorContext ctx, String requestedClass) throws UnableToCompleteException {
        TypeOracle typeOracle = ctx.getTypeOracle();
        assert (typeOracle != null);

        JClassType remoteService = typeOracle.findType(requestedClass);
        if (remoteService == null) {
            logger.log(TreeLogger.ERROR, "Unable to find metadata for type '" + requestedClass + "'");
            throw new UnableToCompleteException();
        }

        if (remoteService.isInterface() == null) {
            logger.log(TreeLogger.ERROR, remoteService.getQualifiedSourceName() + " is not an interface");
            throw new UnableToCompleteException();
        }

        TreeLogger proxyLogger = logger.branch(TreeLogger.DEBUG, "Generating client proxy for remote service interface '"
                + remoteService.getQualifiedSourceName() + "'");

        return new UberProxyCreator(remoteService).create(proxyLogger, ctx);
    }

}
